﻿// © 2009 Microsoft Corporation.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using Microsoft.Security.Application;

namespace Microsoft.InformationSecurity.RiskManagement.ISRMWeb.UserControls
{
    public partial class SearchFilterControl : System.Web.UI.UserControl
    {
        public event EventHandler<SearchFilterResultEventArgs> SearchFilterSelected;
        public event EventHandler<SearchFilterResultEventArgs> SearchFilterLoaded;

        string strFieldXml = "";
        bool blnSortFields;
        List<SearchFilterField> lstSearchFields = null;
        public string FieldsXml 
        {
            get 
            {
                return strFieldXml;
            } 
            set
            {
                strFieldXml = value;
                
            }
        }
        public string BusinessObjectType {get;set;}
        public bool SortFields 
        {
            get { return blnSortFields;  }
            set
            {
                blnSortFields = value;
                if (blnSortFields)
                    this.SortFieldsDropDown();
            }
        }

        public string ButtonText 
        {
            set { btnApply.Text=value; }
            get { return btnApply.Text; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(this.FieldsXml))
            {
                lstSearchFields = this.LoadFields();
                txtValue.Focus();
            }
            if (!Page.IsPostBack)
            {
                if (lstSearchFields.Count > 0)
                {
                    foreach (SearchFilterField field in lstSearchFields)
                    {
                        ddlFields.Items.Add(new ListItem(field.DisplayName,field.Name));
                        if (field.IsDefault)
                            ddlFields.Items.FindByValue(field.Name).Selected = true;
                    }

                }
                if (blnSortFields)
                    this.SortFieldsDropDown();

                this.LoadOperatorsAndValues();
                SearchFilterResult result = GetSelectedResult();
                this.OnSearchFilterLoaded(result);

                Page.ClientScript.RegisterStartupScript(this.GetType(), "GetClientUTCOffset", "<script lanauge='javascript'>GetClientUTCOffset('" + hiddenClientUTCOffset.ClientID + "');</script>");                
            }
        }

        protected void ddlFields_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.LoadOperatorsAndValues();
        }

        private void LoadOperatorsAndValues() 
        {
            foreach (SearchFilterField field in lstSearchFields)
            {
                if (field.Name == ddlFields.SelectedItem.Value)
                {
                    
                    ddlOperators.Items.Clear();
                    foreach (KeyValuePair<string,bool> kvp in field.Operators)
                    {
                        ddlOperators.Items.Add(kvp.Key);
                        if (kvp.Value)
                            ddlOperators.Items.FindByText(kvp.Key).Selected = true;
                    }
                    
                    this.HideControls();
                    validationSummary.Enabled = true;
                    
                    switch (field.DisplayType)
                    {
                        case "TextBox":
                            lblValue.Visible = true;
                            txtValue.Visible = true;
                            txtValue.Text = "";

                            if (field.AllowedValues.Count==1)
                            {
                                txtValue.Text = field.AllowedValues[0].Value;
                            }
                            if (field.IsRequired)
                            {
                                valueRequired.Enabled = true;
                            }
                            if (field.ValidCharacters != "")
                            {
                                FilteredTextBoxExtender1.Enabled = true;
                                FilteredTextBoxExtender1.ValidChars = field.ValidCharacters;
                            }
                            else
                            {
                                FilteredTextBoxExtender1.Enabled = true;
                            }
                                
                            break;
                        case "DropDownList":
                            lblValue.Visible = true;
                            ddlValue.Visible = true;
                            ddlValue.Items.Clear();
                            foreach (AllowedValue av in field.AllowedValues)
                            {
                                ddlValue.Items.Add(new ListItem(av.Value, av.Key.ToString()));
                                if (av.IsDefault)
                                    ddlValue.Items.FindByText(av.Value).Selected = true;
                            }
                            break;
                        case "DateRange":
                            lblFrom.Visible = true;
                            lblTo.Visible = true;
                            txtFromDate.Text = "";
                            txtToDate.Text = "";
                            txtFromDate.Visible = true;
                            txtToDate.Visible = true;
                            toDateValidator.Enabled = true ;
                            fromDateValidator.Enabled = true;
                            toRequired.Enabled = true;
                            fromRequired.Enabled = true;
                            if (field.AllowedValues.Count == 2)
                            {
                                txtFromDate.Text = field.AllowedValues[0].Value;
                                txtToDate.Text = field.AllowedValues[1].Value;
                            }
                            break;
                    }
                    break;
                }
            }
            
        }

        private void HideControls() 
        {
            lblValue.Visible = false;
            txtValue.Visible = false;
            ddlValue.Visible = false;
            lblFrom.Visible = false;
            lblTo.Visible = false;
            txtFromDate.Visible = false;
            txtToDate.Visible = false;
            validationSummary.Enabled = false;
            valueRequired.Enabled = false;
            toDateValidator.Enabled = false;
            fromDateValidator.Enabled = false;
            toRequired.Enabled = false;
            fromRequired.Enabled = false;
        }

        protected void btnApply_Click(object sender, EventArgs e)
        {
            if (ddlFields.SelectedItem != null && Page.IsValid)
            {
                SearchFilterResult result = GetSelectedResult();
                this.OnSearchFilterSelected(result);
            }
        }

        private SearchFilterResult GetSelectedResult()
        {
            SearchFilterResult result = new SearchFilterResult();
            result.FieldName = ddlFields.SelectedItem.Value;
            result.Operator = ddlOperators.SelectedItem.Text;
            if (txtValue.Visible == true)
            {
                result.Values = new string[] { txtValue.Text };
            }
            else if (ddlValue.Visible == true && ddlValue.SelectedItem != null)
            {
                result.Values = new string[] { ddlValue.SelectedItem.Value };
            }
            else if (txtToDate.Visible == true && txtFromDate.Visible == true)
            {
                /* 1.Add time
                 * 2.Convert Local datetime to UTC datetime */
                DateTime dtFrom = DateTime.Now;
                DateTime dtTo = DateTime.Now;
                double clientUTCOffset = 0;
                if (DateTime.TryParse(txtFromDate.Text + " 00:00:00", out dtFrom)
                    && DateTime.TryParse(txtToDate.Text + " 23:59:59", out dtTo))
                {
                    if (double.TryParse(hiddenClientUTCOffset.Value, out clientUTCOffset)
                        && (result.FieldName.Equals("Risk Created Date", StringComparison.InvariantCultureIgnoreCase)
                            || result.FieldName.Equals("CreatedDate", StringComparison.InvariantCultureIgnoreCase)))
                    {
                        // Convert to UTC datetime
                        result.Values = new string[] { dtFrom.AddMinutes(clientUTCOffset).ToString(), dtTo.AddMinutes(clientUTCOffset).ToString() };
                    }
                    else
                    {
                        result.Values = new string[] { dtFrom.ToString(), dtTo.ToString() };
                    }
                }
                else
                {
                    result.Values = new string[] { txtFromDate.Text, txtToDate.Text };
                }
            }
            return result;
        }

        public SearchFilterResult SelectedFilterResult 
        {
            get 
            {
                return this.GetSelectedResult();
            }
        }

        private void OnSearchFilterSelected(SearchFilterResult result) 
        {
            if (this.SearchFilterSelected != null && result != null)
                this.SearchFilterSelected(this, new SearchFilterResultEventArgs(result));
        }

        private void OnSearchFilterLoaded(SearchFilterResult result)
        {
            if (this.SearchFilterLoaded != null && result != null)
                this.SearchFilterLoaded(this, new SearchFilterResultEventArgs(result));
        }

        public void SortFieldsDropDown()
        {
            if (ddlFields.Items.Count > 0)
            {
                ListItem[] sorted = new ListItem[ddlFields.Items.Count];
                for (int i = 0; i < sorted.Length; i++)
                {
                    sorted[i] = ddlFields.Items[i];
                }

                Array.Sort(sorted,new ListItemComparer());
                
                ddlFields.Items.Clear();
                ddlFields.Items.AddRange(sorted);
            }
        }

        private List<SearchFilterField> LoadFields() 
        {
            List<SearchFilterField> lstFields = new List<SearchFilterField>();
            if (!string.IsNullOrEmpty(this.FieldsXml))
            {
                XPathDocument fieldsXmlDoc = new XPathDocument(new StringReader(this.FieldsXml));
                XPathNavigator navDoc = fieldsXmlDoc.CreateNavigator();
                XPathNodeIterator fields = navDoc.Select("/SearchFilterFieldsControlData/SearchFilterFields[@ObjectType='" + AntiXss.XmlEncode(this.BusinessObjectType) + "']/SearchFilterField");
                if (fields.Count > 0)
                {
                    while (fields.MoveNext())
                    {
                        XPathNavigator currentField = fields.Current;
                        SearchFilterField field = new SearchFilterField();
                        field.Name = currentField.GetAttribute("Name", "");
                        field.DisplayType = currentField.GetAttribute("DisplayType", "");
                        field.DataType = currentField.GetAttribute("DataType", "");
                        if (currentField.GetAttribute("Default", "") != "")
                        {
                            field.IsDefault = bool.Parse(currentField.GetAttribute("Default", ""));
                        }
                        if (currentField.GetAttribute("Required", "") != "")
                        {
                            field.IsRequired = bool.Parse(currentField.GetAttribute("Required", ""));
                        }
                        field.ValidCharacters = currentField.GetAttribute("ValidCharacters", "");
                        XPathNodeIterator operators = currentField.Select("Operators/Operator");
                        while (operators.MoveNext())
                        {
                            bool isDefault;
                            bool.TryParse(operators.Current.GetAttribute("Default", ""), out isDefault);
                            field.Operators.Add(new KeyValuePair<string, bool>(operators.Current.Value.ToString(), isDefault));
                        }
                        field.DisplayName = currentField.GetAttribute("DisplayName", "");
                        if (field.DisplayName == "")
                            field.DisplayName = field.Name;
                        switch (field.DisplayType)
                        {
                            case "TextBox":
                                XPathNavigator allowedValue = currentField.SelectSingleNode("AllowedValues/AllowedValue");
                                if (allowedValue != null)
                                {
                                    field.AllowedValues.Add(new AllowedValue(0,allowedValue.Value.ToString(),true));
                                }
                                break;
                            case "DropDownList":
                            case "DateRange":
                                field.AllowedValues.Clear();
                                XPathNodeIterator allowedValues = currentField.Select("AllowedValues/AllowedValue");
                                while (allowedValues.MoveNext())
                                {
                                    bool isDefault;
                                    bool.TryParse(allowedValues.Current.GetAttribute("Default", ""), out isDefault);
                                    field.AllowedValues.Add(new AllowedValue(int.Parse(allowedValues.Current.GetAttribute("Key", "")), allowedValues.Current.Value.ToString(), isDefault));
                                }
                                break;
                        }
                        lstFields.Add(field);
                    }
                }
               
            }
            return lstFields;
        }

    }

    public class ListItemComparer : IComparer<ListItem> 
    {

        #region IComparer<ListItem> Members

        public int Compare(ListItem x, ListItem y)
        {
            return string.Compare(x.Text, y.Text);
        }

        #endregion
    }
}